﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//  SmsMessageSender.cs
//    
// Abstract:
//
//  Unit tests for the SmsMessageSender class.
//  
//--

using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Microsoft.OfficeCommunicationsServer.Applications.Common;

namespace Microsoft.EnhancedReminders.Dispatcher.UnitTests
{
    /// <summary>
    ///This is a test class for DispatcherHelpersTest and is intended
    ///to contain all DispatcherHelpersTest Unit Tests
    ///</summary>
    [TestClass()]
    public class SmsMessageSenderTest
    {
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        /// <summary>
        /// Test creating a message for a voicemail reminder.
        /// </summary>
        [TestMethod()]
        public void TestSmsVoicemailReminderBody()
        {
            VoicemailNotificationItem notification = CreateVoicemailNotification("john@contoso.com");
            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Voicemail, "john@contoso.com");
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Test creating a message for a voicemail reminder where we need to truncate
        /// the caller ID.
        /// </summary>
        [TestMethod()]
        public void TestSmsVoicemailReminderBodyTruncated()
        {
            VoicemailNotificationItem notification = CreateVoicemailNotification("johnaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@contoso.com");
            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Voicemail,
                notification.VoicemailCallerId).Substring(0, 160);
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Test creating a SMS message for a calendar reminder where no strings need to
        /// be truncated
        /// </summary>
        [TestMethod()]
        public void TestSmsCalendarReminder()
        {
            CalendarNotificationItem notification = CreateCalendarNotification("Home", "You have an appointment!");
            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Appointment,
                DispatcherHelpers.GetLeadTime(CultureInfo.CurrentUICulture, TimeZoneInfo.Local, DateTime.UtcNow, new SmsTimeSpanFormatter()),
                notification.Message, notification.Location);
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Test creating a SMS message for a meeting reminder where no strings need to
        /// be truncated
        /// </summary>
        [TestMethod()]
        public void TestSmsMeetingReminder()
        {
            MeetingNotificationItem notification = CreateMeetingNotification("Home", "You have an appointment!");
            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Meeting,
                DispatcherHelpers.GetLeadTime(CultureInfo.CurrentUICulture, TimeZoneInfo.Local, DateTime.UtcNow, new SmsTimeSpanFormatter()),
                notification.Message, notification.Location);
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Test creating a SMS message for a calendar reminder where the reminder subject too long and
        /// we have to truncate part of the reminder.
        /// </summary>
        [TestMethod()]
        public void TestSmsCalendarReminderTruncatedSubject()
        {
            CalendarNotificationItem notification = CreateCalendarNotification("You have an appointment!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
                "Home");
            string leadTime = DispatcherHelpers.GetLeadTime(CultureInfo.CurrentUICulture, TimeZoneInfo.Local, DateTime.UtcNow, new SmsTimeSpanFormatter());
            int maxSubjectLocationLength = (160 - (IMResources.Sms_Appointment.Length - (3 * 3) /* length of {1} fields */ + leadTime.Length)) / 2;

            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Appointment, leadTime,
                notification.Message.Substring(0, maxSubjectLocationLength), notification.Location);
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Test creating a SMS message for a calendar reminder where the reminder location is too long and
        /// we have to truncate part of the reminder.
        /// </summary>
        [TestMethod()]
        public void TestSmsCalendarReminderTruncatedLocation()
        {
            CalendarNotificationItem notification = CreateCalendarNotification("You have an appointment",
                "Home!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            string leadTime = DispatcherHelpers.GetLeadTime(CultureInfo.CurrentUICulture, TimeZoneInfo.Local, DateTime.UtcNow, new SmsTimeSpanFormatter());
            int maxSubjectLocationLength = (160 - (IMResources.Sms_Appointment.Length - 9 /* length of {1} fields */ + leadTime.Length)) / 2;

            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Appointment, leadTime,
                notification.Message, notification.Location.Substring(0, maxSubjectLocationLength));
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Test creating a SMS message for a meeting reminder where the reminder subject too long and
        /// we have to truncate part of the reminder.
        /// </summary>
        [TestMethod()]
        public void TestSmsMeetingReminderTruncatedSubject()
        {
            CalendarNotificationItem notification = CreateMeetingNotification("You have an appointment!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
                "Home");
            string leadTime = DispatcherHelpers.GetLeadTime(CultureInfo.CurrentUICulture, TimeZoneInfo.Local, DateTime.UtcNow, new SmsTimeSpanFormatter());
            int maxSubjectLocationLength = (160 - (IMResources.Sms_Meeting.Length - 9 /* length of {1} fields */ + leadTime.Length)) / 2;

            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Meeting, leadTime,
                notification.Message.Substring(0, maxSubjectLocationLength), notification.Location);
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Test creating a SMS message for a meeting reminder where the reminder location is too long and
        /// we have to truncate part of the reminder.
        /// </summary>
        [TestMethod()]
        public void TestSmsMeetingReminderTruncatedLocation()
        {
            MeetingNotificationItem notification = CreateMeetingNotification("You have an appointment",
                "Home!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
            string leadTime = DispatcherHelpers.GetLeadTime(CultureInfo.CurrentUICulture, TimeZoneInfo.Local, DateTime.UtcNow, new SmsTimeSpanFormatter());
            int maxSubjectLocationLength = (160 - (IMResources.Sms_Meeting.Length - 9 /* length of {1} fields */ + leadTime.Length)) / 2;

            string expectedResult = string.Format(CultureInfo.CurrentUICulture, IMResources.Sms_Meeting, leadTime,
                notification.Message, notification.Location.Substring(0, maxSubjectLocationLength));
            string actualResult = SmsMessageSender_Accessor.GetSmsBodyForNotification(notification);

            Assert.AreEqual(expectedResult, actualResult);
        }

        /// <summary>
        /// Creates a generic calendar notification with a given subject and location
        /// </summary>
        /// <param name="subject">The subject of the notification</param>
        /// <param name="location">The location of the notification</param>
        /// <returns>A generic calendar notification item</returns>
        private static CalendarNotificationItem CreateCalendarNotification(string subject, string location)
        {
            return new CalendarNotificationItem(Context.Global, new NotificationId("id", "john@contoso.com"),
                "john@contoso.com", DateTime.UtcNow, new ReminderItem(new List<NotificationChannel>()), "John Contoso", false /* hasBody */,
                location, subject, DateTime.UtcNow);
        }

        /// <summary>
        /// Creates a generic meeting notification with a given subject and location
        /// </summary>
        /// <param name="subject">The subject of the notification</param>
        /// <param name="location">The location of the notification</param>
        /// <returns>A generic meeting notification item</returns>
        private static MeetingNotificationItem CreateMeetingNotification(string subject, string location)
        {
            return new MeetingNotificationItem(Context.Global,
                new NotificationId("id", "john@contoso.com"),
                "john@contoso.com", DateTime.UtcNow, new ReminderItem(new List<NotificationChannel>()), "John Contoso", false /* hasBody */, 
                location, subject, DateTime.UtcNow, "john@contoso.com", false);
        }

        /// <summary>
        /// Creates a generic voicemail notification with a given callerId
        /// </summary>
        /// <param name="callerId">The callerId of the voicemail notification</param>
        /// <returns>A generic voicemail notification item</returns>
        private static VoicemailNotificationItem CreateVoicemailNotification(string callerId)
        {
            return new VoicemailNotificationItem(Context.Global,
                new NotificationId("id", "john@contoso.com"), "john@contoso.com", DateTime.UtcNow, new ReminderItem[] { new ReminderItem(new List<NotificationChannel>()) },
                "John Contoso", null, true, callerId);
        }
    }
}
